#include "firmwareupgradedialog.h"
#include <QApplication>
#include <QDir>
#include <QMessageBox>
#include <QDateTime>
#include <QThread>

FirmwareUpgradeDialog::FirmwareUpgradeDialog(const QString &ipAddress, DeviceManager *deviceManager, QWidget *parent)
    : QDialog(parent)
    , m_ipAddress(ipAddress)
    , m_deviceManager(deviceManager)
    , m_state(Idle)
    , m_forceUpgrade(false)
    , m_totalChunks(0)
    , m_currentChunk(0)
    , m_chunkSize(64 * 1024) // 64KB chunks
{
    setupUI();
    connectSignals();
    updateUI();
    
    // 初始化定时器
    m_statusCheckTimer = new QTimer(this);
    connect(m_statusCheckTimer, &QTimer::timeout, this, &FirmwareUpgradeDialog::onStatusCheckTimer);
    
    // 设置对话框属性
    setWindowTitle(tr("Firmware Upgrade"));
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
    resize(600, 500);
    
    // 添加初始日志
    addLog(QString("Firmware upgrade dialog initialized for device: %1").arg(m_ipAddress));
}

void FirmwareUpgradeDialog::setupUI()
{
    // 主布局
    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    
    // 文件选择组
    m_fileSelectionGroup = new QGroupBox(tr("Firmware File Selection"));
    QGridLayout *fileLayout = new QGridLayout(m_fileSelectionGroup);
    
    m_filePathEdit = new QLineEdit();
    m_selectFileButton = new QPushButton(tr("Browse..."));
    m_fileSizeLabel = new QLabel();
    m_fileMD5Label = new QLabel();
    
    fileLayout->addWidget(new QLabel(tr("File Path:")), 0, 0);
    fileLayout->addWidget(m_filePathEdit, 0, 1);
    fileLayout->addWidget(m_selectFileButton, 0, 2);
    fileLayout->addWidget(new QLabel(tr("File Size:")), 1, 0);
    fileLayout->addWidget(m_fileSizeLabel, 1, 1);
    fileLayout->addWidget(new QLabel(tr("MD5:")), 2, 0);
    fileLayout->addWidget(m_fileMD5Label, 2, 1);
    
    // 升级选项组
    m_upgradeOptionsGroup = new QGroupBox(tr("Upgrade Options"));
    QGridLayout *optionsLayout = new QGridLayout(m_upgradeOptionsGroup);
    
    m_versionEdit = new QLineEdit();
    m_forceCheckBox = new QCheckBox(tr("Force upgrade (recommended for development)"));
    
    optionsLayout->addWidget(new QLabel(tr("Version:")), 0, 0);
    optionsLayout->addWidget(m_versionEdit, 0, 1);
    optionsLayout->addWidget(m_forceCheckBox, 1, 0, 1, 2);
    
    // 进度组
    m_progressGroup = new QGroupBox(tr("Progress"));
    QVBoxLayout *progressLayout = new QVBoxLayout(m_progressGroup);
    
    m_uploadProgressBar = new QProgressBar();
    m_uploadProgressBar->setRange(0, 100);
    m_uploadProgressBar->setValue(0);
    
    m_upgradeProgressBar = new QProgressBar();
    m_upgradeProgressBar->setRange(0, 100);
    m_upgradeProgressBar->setValue(0);
    
    m_statusLabel = new QLabel(tr("Ready"));
    
    m_logTextEdit = new QTextEdit();
    m_logTextEdit->setReadOnly(true);
    
    progressLayout->addWidget(new QLabel(tr("Upload Progress:")));
    progressLayout->addWidget(m_uploadProgressBar);
    progressLayout->addWidget(new QLabel(tr("Upgrade Progress:")));
    progressLayout->addWidget(m_upgradeProgressBar);
    progressLayout->addWidget(new QLabel(tr("Status:")));
    progressLayout->addWidget(m_statusLabel);
    progressLayout->addWidget(new QLabel(tr("Log:")));
    progressLayout->addWidget(m_logTextEdit);
    
    // 按钮
    QHBoxLayout *buttonLayout = new QHBoxLayout();
    m_startButton = new QPushButton(tr("Start Upgrade"));
    m_cancelButton = new QPushButton(tr("Cancel"));
    buttonLayout->addStretch();
    buttonLayout->addWidget(m_startButton);
    buttonLayout->addWidget(m_cancelButton);
    
    // 添加到主布局
    mainLayout->addWidget(m_fileSelectionGroup);
    mainLayout->addWidget(m_upgradeOptionsGroup);
    mainLayout->addWidget(m_progressGroup);
    mainLayout->addLayout(buttonLayout);
}

void FirmwareUpgradeDialog::connectSignals()
{
    connect(m_selectFileButton, &QPushButton::clicked, this, &FirmwareUpgradeDialog::onSelectFileClicked);
    connect(m_startButton, &QPushButton::clicked, this, &FirmwareUpgradeDialog::onStartUpgradeClicked);
    connect(m_cancelButton, &QPushButton::clicked, this, &FirmwareUpgradeDialog::onCancelClicked);
    
    // 连接设备管理器信号
    connect(m_deviceManager, &DeviceManager::firmwareUploadProgress,
            this, &FirmwareUpgradeDialog::onFirmwareUploadProgress);
    connect(m_deviceManager, &DeviceManager::firmwareUploadComplete,
            this, &FirmwareUpgradeDialog::onFirmwareUploadComplete);
    connect(m_deviceManager, &DeviceManager::firmwareUpgradeStarted,
            this, &FirmwareUpgradeDialog::onFirmwareUpgradeStarted);
    connect(m_deviceManager, &DeviceManager::firmwareUpgradeStatusReceived,
            this, &FirmwareUpgradeDialog::onFirmwareUpgradeStatusReceived);
    connect(m_deviceManager, &DeviceManager::firmwareUpgradeError,
            this, &FirmwareUpgradeDialog::onFirmwareUpgradeError);
}

void FirmwareUpgradeDialog::updateUI()
{
    bool hasFile = !m_selectedFilePath.isEmpty();
    
    m_fileSizeLabel->setEnabled(hasFile);
    m_fileMD5Label->setEnabled(hasFile);
    m_versionEdit->setEnabled(hasFile);
    m_forceCheckBox->setEnabled(hasFile);
    m_startButton->setEnabled(hasFile && m_state == Idle);
    
    m_selectFileButton->setEnabled(m_state == Idle);
    m_filePathEdit->setEnabled(m_state == Idle);
    
    // 根据状态更新UI
    switch (m_state) {
    case Idle:
        m_statusLabel->setText(tr("Ready"));
        break;
    case Uploading:
        m_statusLabel->setText(tr("Uploading firmware..."));
        break;
    case UploadComplete:
        m_statusLabel->setText(tr("Upload complete, starting upgrade..."));
        break;
    case Upgrading:
        m_statusLabel->setText(tr("Upgrading firmware..."));
        break;
    case Success:
        m_statusLabel->setText(tr("Upgrade successful!"));
        break;
    case Failed:
        m_statusLabel->setText(tr("Upgrade failed!"));
        break;
    }
}

void FirmwareUpgradeDialog::setUIEnabled(bool enabled)
{
    m_fileSelectionGroup->setEnabled(enabled);
    m_upgradeOptionsGroup->setEnabled(enabled);
    m_startButton->setEnabled(enabled);
}

void FirmwareUpgradeDialog::onSelectFileClicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,
        tr("Select Firmware File"), "", tr("Firmware Files (*.bin *.zip);;All Files (*)"));
    
    if (!fileName.isEmpty()) {
        addLog(QString("Selected firmware file: %1").arg(fileName));
        
        m_selectedFilePath = fileName;
        m_filePathEdit->setText(fileName);
        
        // 显示文件信息
        QFileInfo fileInfo(fileName);
        m_fileSizeLabel->setText(QString("%1 bytes").arg(fileInfo.size()));
        addLog(QString("File size: %1 bytes").arg(fileInfo.size()));
        
        QString md5 = calculateMD5(fileName);
        m_fileMD5Label->setText(md5);
        addLog(QString("File MD5: %1").arg(md5));
        
        // 自动填充版本号（如果未设置）
        if (m_versionEdit->text().isEmpty()) {
            QString version = fileInfo.baseName();
            m_versionEdit->setText(version);
            m_firmwareVersion = version;
            addLog(QString("Auto-filled version: %1").arg(version));
        }
        
        updateUI();
    }
}

void FirmwareUpgradeDialog::onStartUpgradeClicked()
{
    if (m_selectedFilePath.isEmpty()) {
        QMessageBox::warning(this, tr("Warning"), tr("Please select a firmware file first."));
        return;
    }
    
    if (m_versionEdit->text().isEmpty()) {
        QMessageBox::warning(this, tr("Warning"), tr("Please enter a firmware version."));
        return;
    }
    
    m_firmwareVersion = m_versionEdit->text();
    m_forceUpgrade = m_forceCheckBox->isChecked();
    
    addLog(QString("Starting firmware upgrade, version: %1, force: %2").arg(m_firmwareVersion).arg(m_forceUpgrade ? "true" : "false"));
    
    // 开始上传固件
    uploadFirmwareFile();
}

void FirmwareUpgradeDialog::onCancelClicked()
{
    if (m_state == Uploading || m_state == Upgrading) {
        int ret = QMessageBox::question(this, tr("Confirm Cancel"), 
            tr("Are you sure you want to cancel the upgrade process?"));
        if (ret == QMessageBox::Yes) {
            m_state = Failed;
            m_statusCheckTimer->stop();
            updateUI();
            addLog(tr("Firmware upgrade cancelled by user."));
        }
    } else {
        addLog(tr("Dialog closed."));
        reject();
    }
}

void FirmwareUpgradeDialog::onFirmwareUploadProgress(const QString &ipAddress, int progress)
{
    if (ipAddress == m_ipAddress) {
        m_uploadProgressBar->setValue(progress);
        if (progress % 10 == 0) {  // 每10%记录一次日志
            addLog(QString("Firmware upload progress: %1%").arg(progress));
        }
    }
}

void FirmwareUpgradeDialog::onFirmwareUploadComplete(const QString &ipAddress)
{
    if (ipAddress == m_ipAddress) {
        m_state = UploadComplete;
        m_uploadProgressBar->setValue(100);
        updateUI();
        addLog(tr("Firmware upload completed, starting upgrade..."));

        m_deviceManager->startFirmwareUpgrade(m_ipAddress, m_firmwareVersion, m_forceUpgrade);
    }
}

void FirmwareUpgradeDialog::onFirmwareUpgradeStarted(const QString &ipAddress, const QString &upgradeId, 
                                                    const QString &status, int estimatedDuration)
{
    if (ipAddress == m_ipAddress) {
        m_state = Upgrading;
        updateUI();
        addLog(QString("Firmware upgrade started, upgrade ID: %1, status: %2").arg(upgradeId, status));
        
        // 启动定时器定期查询状态
        m_statusCheckTimer->start(2000); // 每2秒查询一次
    }
}

void FirmwareUpgradeDialog::onFirmwareUpgradeStatusReceived(const QString &ipAddress, 
                                                           const QString &status, int progress, 
                                                           const QString &message)
{
    if (ipAddress == m_ipAddress) {
        m_upgradeProgressBar->setValue(progress);
        addLog(QString("Upgrade status: %1, progress: %2%, message: %3").arg(status).arg(progress).arg(message));
        
        // 更新状态显示
        if (status == "completed") {
            m_state = Success;
            m_statusCheckTimer->stop();
            updateUI();
            addLog(tr("Firmware upgrade completed successfully!"));
            QMessageBox::information(this, tr("Success"), tr("Firmware upgrade completed successfully!"));
        } else if (status == "failed") {
            m_state = Failed;
            m_statusCheckTimer->stop();
            updateUI();
            addLog(tr("Firmware upgrade failed: %1").arg(message));
            QMessageBox::critical(this, tr("Error"), tr("Firmware upgrade failed: %1").arg(message));
        } else if (status == "upgrading") {
            // 升级中状态，继续查询
            m_state = Upgrading;
            updateUI();
        } else if (status == "rebooting") {
            // 重启状态
            addLog(tr("Device is rebooting..."));
        }
    }
}

void FirmwareUpgradeDialog::onFirmwareUpgradeError(const QString &ipAddress, const QString &errorMessage)
{
    if (ipAddress == m_ipAddress) {
        m_state = Failed;
        m_statusCheckTimer->stop();
        updateUI();
        addLog(tr("Firmware upgrade error: %1").arg(errorMessage));
        QMessageBox::critical(this, tr("Error"), tr("Firmware upgrade error: %1").arg(errorMessage));
    }
}

void FirmwareUpgradeDialog::onStatusCheckTimer()
{
    // 定期查询设备升级状态
    m_deviceManager->getFirmwareUpgradeStatus(m_ipAddress);
}

void FirmwareUpgradeDialog::uploadFirmwareFile()
{
    addLog(QString("Starting firmware upload: %1").arg(m_selectedFilePath));
    
    QFile file(m_selectedFilePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::critical(this, tr("Error"), tr("Failed to open firmware file."));
        addLog(tr("Failed to open firmware file."));
        return;
    }
    
    m_fileData = file.readAll();
    file.close();
    
    if (m_fileData.isEmpty()) {
        QMessageBox::critical(this, tr("Error"), tr("Firmware file is empty."));
        addLog(tr("Firmware file is empty."));
        return;
    }
    
    m_totalChunks = (m_fileData.size() + m_chunkSize - 1) / m_chunkSize;
    m_currentChunk = 0;
    m_state = Uploading;
    updateUI();
    addLog(QString("File size: %1 bytes, total chunks: %2").arg(m_fileData.size()).arg(m_totalChunks));
    
    // 上传第一个块
    sendNextChunk();
}

void FirmwareUpgradeDialog::sendNextChunk()
{
    if (m_currentChunk >= m_totalChunks) {
        return;
    }
    
    int start = m_currentChunk * m_chunkSize;
    int end = qMin(start + m_chunkSize, m_fileData.size());
    QByteArray chunk = m_fileData.mid(start, end - start);
    
    QFileInfo fileInfo(m_selectedFilePath);
    QString fileName = fileInfo.fileName();
    qint64 fileSize = fileInfo.size();
    QString md5 = calculateMD5(m_selectedFilePath);
    
    m_deviceManager->uploadFirmware(m_ipAddress, m_currentChunk, m_totalChunks, chunk,
                                   fileName, fileSize, m_firmwareVersion, md5);
    
    m_currentChunk++;
    
    // 如果还有更多块，继续发送
    if (m_currentChunk < m_totalChunks) {
        // 使用单次定时器来避免阻塞UI，增加适当延时避免服务器过载
        QTimer::singleShot(10, this, &FirmwareUpgradeDialog::sendNextChunk);
    }
}

void FirmwareUpgradeDialog::addLog(const QString &message)
{
    QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    QString logMessage = QString("[%1] %2").arg(timestamp, message);
    
    m_logTextEdit->append(logMessage);
    
    // 滚动到底部
    QTextCursor cursor = m_logTextEdit->textCursor();
    cursor.movePosition(QTextCursor::End);
    m_logTextEdit->setTextCursor(cursor);
}

QString FirmwareUpgradeDialog::calculateMD5(const QString &filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        return QString();
    }
    
    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(&file);
    file.close();
    
    return hash.result().toHex();
}